package com.bm.main;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import com.bm.model.Message;
import com.bm.util.*;
import java.io.*;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author dellapramukti
 */
public class MISMS implements Runnable {
    
    
    private PropertiesHandler properties;
    Calendar calendar = Calendar.getInstance();
    java.sql.Date startDate = new java.sql.Date(calendar.getTime().getTime());    
    Thread incoming = null;
    Thread runOutbox = null;
    Thread runSentTrash = null;
    Thread deleteTrash = null;
    Thread moveFailed = null;
    Thread moveBuffer = null;
    Thread terminateApp = null;
    int second = calendar.get(Calendar.SECOND);
    String dir_root = "";
    String dir_in = "";
    String dir_in_trash = "";
    String dir_out = "";
    String dir_outbuff = "";
    String dir_invalid = "";
    String dir_sent = "";
    String dir_sent_trash = "";
    String dir_failed = "";
    String id_modul = "";
    private boolean started = true;
    private static boolean terminate = true;
    private final String LOG_FILENAME = "log.txt";

    public MISMS(boolean tampilkanMessage, boolean tampilkanLog, String id_modul) throws IOException {
        properties=new PropertiesHandler();
        MessagePrinter.enablePrint = tampilkanMessage;
        MessagePrinter.printLog = tampilkanLog;        
        this.id_modul = id_modul;
        if (!tampilkanMessage) {
            System.out.println("Tampilan berita dimatikan. Untuk mengaktifkan, silahkan tambahkan true setelah pemanggilan nama file jar [java -jar nama.jar true].");
        }
        initDir();
    }

    private void initDir() {
        this.dir_root = properties.getrootDirectory();
        this.dir_in = this.dir_root + "incoming/";
        this.dir_in_trash = this.dir_root + "incoming_trash/";
        this.dir_out = this.dir_root + "outgoing/";
        this.dir_outbuff = this.dir_root + "outgoing_buffer/";
        this.dir_invalid = this.dir_root + "invalid/";
        this.dir_sent = this.dir_root + "sent/";
        this.dir_sent_trash = this.dir_root + "sent_trash/";
        this.dir_failed = this.dir_root + "failed/";
    }

    void tampilBerita(String msg) {
        MessagePrinter.print("[" + formatWaktu(new Date(), null) + "] " + msg + "\n");
    }

    public void showErrMsg(String msg) {
        MessagePrinter.printLog("Error Message", msg);
    }

    public void writeLog(Object teks) {
        try {
            // Create file
            FileWriter fstream = new FileWriter(LOG_FILENAME, true);
            BufferedWriter bf = new BufferedWriter(fstream);
            bf.newLine();
            bf.close();
        } catch (Exception e) {//Catch exception if any
        }
    }

    public static String formatWaktu(Date waktu, String fmt) {
        Format formatter;
        if (fmt == null) {
            fmt = "dd/MM HH:mm:ss";
        }
        formatter = new SimpleDateFormat(fmt);

        return formatter.format(waktu);
    }

    @Override
    public void run() {
        started = true;
        incoming = new Thread() {
            @Override
            public void run() {
                while (started) {
                    try {
                        if (!dir_root.equalsIgnoreCase("")) {
                            incoming();
                        }
                        Thread.sleep(Integer.parseInt(properties.getIncomingInterval()) * 1000);
                    } catch (Exception ex) {
                        ////Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        runOutbox = new Thread() {
            @Override
            public void run() {
                while (started) {
                    try {
                        if (!dir_root.equalsIgnoreCase("")) {
                            outgoing();
                        }
                        Thread.sleep(Integer.parseInt(properties.getOutboxInterval()) * 1000);
                    } catch (Exception ex) {
                        ////Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        runSentTrash = new Thread() {
            @Override
            public void run() {
                while (started) {
                    try {
                        if (!dir_root.equalsIgnoreCase("")) {
                            sentTrash();
                        }
                        Thread.sleep(Integer.parseInt(properties.getSentInterval()) * 1000);
                    } catch (Exception ex) {
                        ////Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        deleteTrash = new Thread() {
            @Override
            public void run() {
                while (started) {
                    try {
                        if (!dir_root.equalsIgnoreCase("")) {
                            deleteSentTrash();
                            deleteIncomingTrash();
                            deleteFailed();
                        }
                        Thread.sleep(Integer.parseInt(properties.getDeleteTrashInterval()) * 1000);
                    } catch (Exception ex) {
                        //Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        moveFailed = new Thread() {
            @Override
            public void run() {
                while (started) {
                    try {
                        if (!dir_root.equalsIgnoreCase("")) {
                            moveFailed();
                        }
                        Thread.sleep(Integer.parseInt(properties.getMoveFailedInterval()) * 1000);
                    } catch (Exception ex) {
                        //Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        moveBuffer = new Thread() {
            @Override
            public void run() {
                try {
                    while (started) {
                        moveBuffer();
                        Thread.sleep(Integer.parseInt(properties.getMoveBufferInterval()) * 1000);
                    }
                } catch (InterruptedException ex) {
                    Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };

        terminateApp = new Thread() {
            @Override
            public void run() {
                try {
                    while (started) {
                        checkTerminateApp();
                        Thread.sleep(Integer.parseInt(properties.getTerminateAppInterval()) * 1000);
                    }
                } catch (InterruptedException ex) {
                    Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };

        incoming.start();
        runOutbox.start();
        runSentTrash.start();
        deleteTrash.start();
        moveFailed.start();
        moveBuffer.start();
        terminateApp.start();
    }

    public static void checkTerminateApp() {
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sd = new SimpleDateFormat("mm");
        int minute = Integer.valueOf(sd.format(c.getTime()));

        c = Calendar.getInstance();
        sd = new SimpleDateFormat("HH");
        int hour = Integer.valueOf(sd.format(c.getTime()));

        if (hour >= 23 && minute >= 55) {
            System.out.println("Processing shutdown");
            System.exit(0);
        } else {
            System.out.println("Shutdown not processed (" + hour + ":" + minute + ")");
        }
    }

    public void moveBuffer() {
        String path = this.dir_outbuff;
        File folder = new File(path);
        if (folder.exists()) {
            String files;
            File file;
            String fname;
            File outgoing;
            File[] listOfFiles = folder.listFiles();
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    files = listOfFiles[i].getName();
                    if (!files.startsWith("smsd_script.")) {
                        Calendar calendarx = Calendar.getInstance();
                        calendarx.add(Calendar.SECOND, -1);
                        Date d = new Date(listOfFiles[i].lastModified());
                        if (d.before(calendarx.getTime())) {
                            file = new File(path + files);
                            fname = dir_out + file.getName();
                            outgoing = new File(fname);
                            if (outgoing.exists()) {
                                outgoing.delete();
                            }
                            boolean status = file.renameTo(outgoing);
                            MessagePrinter.printLog("MEMINDAH BUFFER KE OUTGOING", "");
                            if (status) {
                                tampilBerita(files + " buffer berhasil dipindah ke directory outgoing.");
                            } else {
                                tampilBerita(files + " buffer gagal dipindah ke directory outgoing.");
                            }
                        }
                    }
                }
            }
        }
    }

    public void incoming() throws IOException, Exception {
        String path = this.dir_in;
        File folder = new File(path);
        if (folder.exists()) {
            int step = 1;
            String sender = "";
            String receiver = "";
            String via = "SMS";
            int is_sent = 0;
            String files;
            File file;
            Scanner scanner;
            String txtLine;
            String fname;
            File[] listOfFiles = folder.listFiles();
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    files = listOfFiles[i].getName();
                    if (!files.startsWith("smsd_script.")) {
                        File incoming_trash = null;
                        file = new File(path + files);

                        long datetime = file.lastModified();
                        Date d = new Date(datetime);
                        SimpleDateFormat sd = new SimpleDateFormat("dd");
                        String tanggalFile = sd.format(d);

                        Calendar c = Calendar.getInstance();
                        sd = new SimpleDateFormat("dd");
                        String tanggalSekarang = sd.format(c.getTime());

                        String content = "";
                        boolean status = false;
                        try {
                            scanner = new Scanner(file);
                            int m = 0;
                            int iStatic = 0;
                            String sentDate = "";
                            while (scanner.hasNextLine()) {
                                txtLine = scanner.nextLine();

                                if (iStatic == 3) {
                                    try {
                                        sentDate = txtLine.substring(6).trim();
                                        sentDate = MrStringUtil.convertDate(sentDate);
                                        System.out.println("Send Date : " + sentDate);
                                    } catch (Exception e) {
                                    }
                                }
                                
                                if (iStatic == 6){
                                    receiver = txtLine.substring(7).trim();
                                    System.out.println("Receiver : " + receiver);
                                }

                                if (m == 0) {
                                    sender = txtLine.substring(6).trim();
                                    m = 1;
                                }

                                if (txtLine.trim().equalsIgnoreCase("")) {
                                    m = 2;
                                } else if (m == 2) {
                                    m = 3;
                                }

                                if (m == 3) {
                                    content += txtLine.trim();
                                }
                                iStatic++;
                            }
                            scanner.close();

                            if (sender.startsWith("62")) {
                                sender = sender.replaceFirst("62", "0");
                            } else if (sender.startsWith("+62")) {
                                sender = sender.replaceFirst("+62", "0");
                            }
                            content = content.replace("\u0000", "");
                            content.trim();                            

                            fname = dir_in_trash + file.getName();
                            incoming_trash = new File(fname);
                            if (incoming_trash.exists()) {
                                MessagePrinter.printLog("delete existing file in trash");
                                incoming_trash.delete();
                            }
                            status = file.renameTo(incoming_trash);
                            MessagePrinter.printLog("MEMINDAH KE INCOMING TRASH", file.getAbsolutePath() + " => " + incoming_trash.getAbsolutePath() + " (status = " + status + ")");

                            if (tanggalFile.equals(tanggalSekarang)) {
                                final Object[] data = {step, sender, receiver, content, this.id_modul, via, is_sent, sentDate};
                                final SocketChecker sc = new SocketChecker();


                                Thread t = new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        sc.getSocketClient().execute("MISMS.insertIntoInbox", data);
                                    }
                                });
                                t.start();


                            } else {
                                MessagePrinter.printLog("File ", file.getAbsolutePath() + " Tidak diproses karena (" + tanggalFile + ") <> (" + tanggalSekarang + ")");
                            }

                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (status) {
                            tampilBerita(files + " berhasil dipindah ke directory incoming_trash.");
                        } else {
                            tampilBerita(files + " gagal dipindah ke incoming_trash.");
                        }
                    }
                }
            }
        }
    }

    public void outgoing() throws IOException, Exception {
        try {
            File folder = new File(this.dir_out);
            if (folder.exists()) {
                Object[] dummy = {"dummy"};
                SocketChecker sc = new SocketChecker();
                MrResultSetAdapter rs = (MrResultSetAdapter) sc.getSocketClient().execute("MISMS.selectFromMessageOutbox", dummy);
                Message message;
                while (rs.next()) {
                    message = new Message();
                    message.setId_message(rs.getInt("id_message"));
                    message.setId_modul(rs.getString("id_modul"));
                    if (rs.getString("receiver") != null && rs.getString("receiver").startsWith("0")) {
                        message.setReceiver(rs.getString("receiver").replaceFirst("0", "62"));
                    } else {
                        message.setReceiver("");
                    }
                    message.setContent(rs.getString("content"));
                    MessagePrinter.printLog("[" + Fungsi.getDetailTime() + "] " + rs.getInt("id_message") + " prepare isi outbox");
                    new IsiOutbox(message, this).start();
                }
            }
        } catch (SQLException ex) {
            //Logger.getLogger(MISMS.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sentTrash() throws Exception {
        String path = this.dir_sent;
        File folder = new File(path);
        if (folder.exists()) {
            String qry = "";
            String files;
            File pindah;
            File sent_trash;
            int id_message;
            File[] listOfFiles = folder.listFiles();

            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    files = listOfFiles[i].getName();
                    if (files.endsWith(".txt") || files.endsWith(".TXT")) {
                        pindah = new File(path + files);
                        id_message = Integer.parseInt(files.replace(".txt", ""));
                        final Object[] data = {id_message, "1"};
                        final SocketChecker sc = new SocketChecker();


                        Thread t = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                sc.getSocketClient().execute("MISMS.updateMessageOutbox", data);
                            }
                        });
                        t.start();

                        sent_trash = new File(dir_sent_trash + pindah.getName());
                        if (sent_trash.exists()) {
                            sent_trash.delete();
                        }
                        boolean status = pindah.renameTo(sent_trash);                        
                        MessagePrinter.printLog("MEMINDAH KE SENT TRASH", pindah.getAbsolutePath() + " => " + sent_trash.getAbsolutePath() + " (status = " + status + ")");
                        if (status) {
                            tampilBerita(files + " berhasil dipindah ke directory sent_trash.");
                        } else {
                            tampilBerita(files + " gagal dipindah ke sent_trash.");
                        }
                    }
                }
            }
        }
    }

    public void deleteSentTrash() throws Exception {
        Calendar calendarx = Calendar.getInstance();
        calendarx.add(Calendar.HOUR, -1);
        deleteFileBefore(this.dir_sent_trash, calendarx.getTime());
    }

    public void deleteIncomingTrash() throws Exception {
        Calendar calendarx = Calendar.getInstance();
        calendarx.add(Calendar.HOUR, -1);
        deleteFileBefore(this.dir_in_trash, calendarx.getTime());
    }

    public void deleteFailed() throws Exception {
        Calendar calendarx = Calendar.getInstance();
        calendarx.add(Calendar.DATE, -1);
        deleteFileBefore(this.dir_failed, calendarx.getTime());
    }

    public void deleteFileBefore(String location, Date limitTime) throws Exception {
        String path = location;
        File folder = new File(path);
        if (folder.exists()) {

            String files;
            File deleteFile;
            long datetime;
            Date d;
            boolean success;
            File[] listOfFiles = folder.listFiles();

            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    files = listOfFiles[i].getName();
                    deleteFile = new File(location + "/" + files);

                    datetime = deleteFile.lastModified();
                    d = new Date(datetime);

                    if (d.before(limitTime)) {
                        success = deleteFile.delete();

                        if (!success) {
                            tampilBerita(deleteFile + " gagal dihapus.");
                        } else {
                            tampilBerita(deleteFile + " berhasil dihapus.");
                        }
                    }
                }
            }
        }
    }

    public void moveFailed() throws Exception {
        String path = this.dir_failed;
        File folder = new File(path);
        if (folder.exists()) {
            PreparedStatement ps = null;

            String files;
            File pindah;
            long datetime;
            Date d;
            Calendar calendarx;
            Date yesterday;
            File sent_trash;
            File[] listOfFiles = folder.listFiles();
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    files = listOfFiles[i].getName();
                    pindah = new File(path + files);

                    datetime = pindah.lastModified();
                    d = new Date(datetime);

                    calendarx = Calendar.getInstance();
                    calendarx.add(Calendar.HOUR_OF_DAY, -1);
                    yesterday = calendarx.getTime();

                    if (d.after(yesterday)) {
                        if (getDateCreatedFile(files.replaceAll(".txt", "")) != null) {
                            if (getDateCreatedFile(files.replaceAll(".txt", "")).after(yesterday)) {
                                sent_trash = new File(this.dir_out + pindah.getName());
                                if (sent_trash.exists()) {
                                    sent_trash.delete();
                                }

                                if (pindah.renameTo(sent_trash)) {
                                    tampilBerita(files + " berhasil dipindah ke directory outgoing.");
                                } else {
                                    tampilBerita(files + " gagal dipindah ke directory outgoing.");
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public Date getDateCreatedFile(String messageId) throws IOException {
        Object[] data = {messageId};
        SocketChecker sc = new SocketChecker();
        java.util.Date d = (java.util.Date) sc.getSocketClient().execute("MISMS.getDateCreatedFile", data);
        return d;
    }
}